﻿using System;
using System.Linq;
using vBridge.Dwm.Aero.AeroAvailabilityCheckers;
using vBridge.Dwm.Aero.Margins;

namespace vBridge.Dwm.Aero.Glassers
{
    /// <summary>
    ///     Wraps a window aero-glasser that will only be called if the system allows aero glasses.
    /// </summary>
    public class SafeAeroGlass : IWindowAeroGlasser
    {
        private readonly IAeroAvailabilityChecker[] _availabilityCheckers;
        private readonly IWindowAeroGlasser _windowAeroGlasser;

        /// <summary>
        ///     Initializes a new instance of the <see cref="SafeAeroGlass" /> class.
        /// </summary>
        /// <param name="windowAeroGlasser">The aero-glasser used if possible to use one.</param>
        /// <param name="availabilityCheckers">The checkers that will see if it is currently possible to aero-glass windows.</param>
        public SafeAeroGlass(IWindowAeroGlasser windowAeroGlasser,
            params IAeroAvailabilityChecker[] availabilityCheckers)
        {
            _windowAeroGlasser = windowAeroGlasser;
            _availabilityCheckers = availabilityCheckers;
        }

        /// <summary>
        ///     Attempts to aero-glass the window.
        /// </summary>
        /// <remarks>
        ///     The method checks if aero-glassing is possible.
        ///     If not, it immediately returns false without trying to glass.
        ///     If it is possible, it will aero-glass the window and return true.
        ///     This method only calls <see cref="TryGlassWindow" /> and discards the return value.
        /// </remarks>
        /// <param name="margins">The margins that will be used to glass.</param>
        public void GlassWindow(IMargins margins)
        {
            TryGlassWindow(margins);
        }

        public IntPtr WindowHandle
        {
            get { return _windowAeroGlasser.WindowHandle; }
        }

        /// <summary>
        ///     Attempts to aero-glass the window.
        /// </summary>
        /// <remarks>
        ///     The method checks if aero-glassing is possible.
        ///     If not, it immediately returns false without trying to glass.
        ///     If it is possible, it will aero-glass the window and return true.
        /// </remarks>
        /// <param name="margins">The margins that will be used to glass.</param>
        /// <returns>Whether the system can aero-glass.</returns>
        public Boolean TryGlassWindow(IMargins margins)
        {
            if (_availabilityCheckers.Any(checker => !checker.IsEnabled()))
                return false;

            _windowAeroGlasser.GlassWindow(margins);
            return true;
        }
    }
}